package net.pulseproject.router.systemtest;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

import java.util.Arrays;

import javax.sound.midi.ShortMessage;

import net.pulseproject.commons.gui.CommonsGuiGuiceModule;
import net.pulseproject.commons.midi.DebuggerLogic;
import net.pulseproject.commons.midi.MessageAnalyzer;
import net.pulseproject.commons.midi.MessageAnalyzerImpl;
import net.pulseproject.commons.midi.RouterMidiGuiceModule;
import net.pulseproject.commons.midi.entity.MidiSocket;
import net.pulseproject.commons.misc.CommonsMiscGuiceModule;
import net.pulseproject.commons.util.MidiUtil;
import net.pulseproject.router.app.RouterApp;
import net.pulseproject.router.app.RouterAppGuiceModule;
import net.pulseproject.router.app.gui.Event.ExecuteConfigurationEvent;
import net.pulseproject.router.app.misc.MainPresenter;
import net.pulseproject.router.config.RouterConfigGuiceModule;
import net.pulseproject.router.config.parser.LineConfig;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.testng.annotations.AfterMethod;

import com.google.inject.Guice;
import com.google.inject.Injector;

/*
 * TODO make use of testNG's guice feature
 * see: http://testng.org/doc/documentation-main.html#guice-dependency-injection
@Guice(modules = GuiceExampleModule.class)
public class GuiceTest extends SimpleBaseTest {
 
  @Inject
  ISingleton m_singleton;
 
  @Test
  public void singletonShouldWork() {
    m_singleton.doSomething();
  }
 
}
 */
public abstract class AbstractSystemTestCase {

	private static final Log LOG = LogFactory.getLog(AbstractSystemTestCase.class);
	
	protected static final String PORT_A = "IAC Driver - Chrisi A";
	
	protected static final String PORT_B = "IAC Driver - Chrisi B";
	
	protected static final String PORT_C = "IAC Driver - Chrisi C";
	
	private final LineConfigSimpleCreator lineConfigCreator = new LineConfigSimpleCreator();

	private final MessageAnalyzer messageAnalyzer = new MessageAnalyzerImpl();
	
	private final DebuggerLogic debuggerLogic = new DebuggerLogic();
	
	private RouterApp app;
	
	@AfterMethod
	public final void quitApplication() throws Exception {
		if(this.app != null) {
			this.app.quit();
			Thread.sleep(100);
			this.app = null;
		}
	}
	
	@SuppressWarnings("boxing")
	protected final void assertMessage(final ShortMessage message, final ShortMessageDescriptor descriptor) {
		assertThat("Messages not equal: descriptor=" + descriptor + ", message=" + MidiUtil.toString(message),
				descriptor.equalsTo(message), equalTo(true));
	}
	
	protected final MidiReceiverCollector newCollector(final MidiSocket socketFilter) {
		return new MidiReceiverCollector(socketFilter, this.messageAnalyzer);
	}
	
	protected final Injector startupApp() {
		final Injector injector = Guice.createInjector(new SystemTestModule());
		
		this.app = injector.getInstance(RouterApp.class);
		LOG.info("JavaApp.startUp() called ...");
		this.app.startUp();
		LOG.info("JavaApp.startUp() finished.");
		return injector;
	}
	
	protected final void executeConfigViaGui(final Injector injector, final LineConfig... configs) {
		final String rawConfigString = new LineConfigTransformer().transform(Arrays.asList(configs));
		// TODO get swing components (insert rawString in JTextArea, and hit JButton) for system-test
		final ExecuteConfigurationEvent event = new ExecuteConfigurationEvent(rawConfigString);
		final MainPresenter presenter = injector.getInstance(MainPresenter.class);
		presenter.onEventDispatched(event);
	}
	
	protected final void sleep(final int sleepingTimeInMs) throws InterruptedException {
		LOG.debug("Sleeping for " + sleepingTimeInMs + "ms ...");
		Thread.sleep(sleepingTimeInMs);
		LOG.debug("Sleeping for " + sleepingTimeInMs + "ms ... DONE");
	}
	
	protected final LineConfigSimpleCreator createConfig() {
		return this.lineConfigCreator;
	}
	
	protected final DebuggerLogic debug() {
		return this.debuggerLogic;
	}
}
